import React, { useState, useEffect, useCallback } from 'react';
import {
  Form,
  Input,
  Button,
  Select,
  message,
  Icon,
  Bubble
} from 'tea-component';
import { HasDeployContractListResponse } from '@ide/types/ideServer';
import useAppStore from '@ide/store';
import { setLocalStorage, getLocalStorage } from '@ide/utils/tools';
import { KeyValueItem, KeyValueList, getListInit } from '@ide/components/common/KeyValueList';
import { ExecResult } from '@ide/components/common/ExecResult';
import { useDeployContractList } from '@/hooks/useDeployContractList';
import { setNotificationEvent } from '@ide/utils/extension';
import { VirtualMachineOptions } from '@ide/utils/enum';
import { invokeAllContractHandler } from '@/api';

export default function ContractCall({ style }: {
  style?: React.CSSProperties;
}) {
  // const { setOutputText } = useAppStore();
  const [contractAddress, setContractAddress] = useState('');
  // 自定义合约方法
  const [customAddress, setCustomAddress] = useState('');
  // 选择的合约方法
  const [contractMethod, setContractMethod] = useState('custom');
  const [customMethod, setCustomMethod] = useState('');
  const [contractOption, setContractOption] = useState([]);
  const [methodOption, setMethodOption] = useState<string[]>([]);
  const { setEditDeployContractsVisible, isPluginReady, deployContracts, getDeployContracts } = useAppStore();
  const [contractMethodRelate, setContractMethodRelate] = useState<{ [x: string]: HasDeployContractListResponse['methods'] }>({});
  // const [submit, setSubmit] = useState(false);
  const [extraList, setExtraList] = useState(getListInit());
  const [platform, setPlatform] = useState<string>('linux_amd64');
  const [chaiId, setchaiId] = useState<string>('');
  const [virtualMachine, setVirtualMachine] = useState('DOCKER_GO');

  // const { list, getDeployContractList } = useDeployContractList();

  useEffect(() => {
    // 获取合约列表
    if (style?.display === 'block') {
      getDeployContracts();
    }
  }, [style?.display]);

  // 获取合约列表
  useEffect(() => {
    const options:any = deployContracts.map((item:any) => ({
      contractName: item.name,
      ...item
    }));
    setContractOption(options);
    setContractAddress(options?.[0]?.contractName);
    setContractMethodRelate(options.reduce((prev: { [x: string]: HasDeployContractListResponse['methods'] }, val: HasDeployContractListResponse) => {
      prev[val.contractName] = val.methods;
      return prev;
    }, {}));
  }, [deployContracts]);

  // 重置数据
  const resetHandle = useCallback(() => {
    setExtraList(getListInit());
    setVirtualMachine('DOCKER_GO');
    setchaiId('');
    setPlatform('linux_amd64');
    setCustomMethod('');
    setContractAddress('');
    setCustomAddress('');
  }, []);
  useEffect(() => {
    setMethodOption(contractMethodRelate?.[contractAddress]);
    // setContractMethod(contractMethodRelate?.[contractAddress]?.[0]);
  }, [contractMethodRelate, contractAddress]);
  // 调用合约
  const invokeContract = useCallback(async () => {
    const name = contractAddress === 'custom' ? customAddress : contractAddress;
    const method = contractMethod === 'custom' ? customMethod : contractMethod;

    if (!name || !method || name.trim() === '' || method.trim() === '') {
      message.error({
        content: '合约地址和合约方法不能为空'
      });
      return;
    }
    if (!chaiId.trim()) {
      message.error({ content: '请输入运行链ID！' });
      return;
    }
    const p = extraList.filter(
      (item) => item.key.trim() !== '' && item.value.trim() !== ''
      ).reduce((val:any, item) => {
        val[item.key] = item.value;
        return val;
      }, {})
    const jsonP = JSON.stringify(p)
    const { code, msg, data } = await invokeAllContractHandler(
      { 
            platform,
            contract_type: virtualMachine, // 'WASMER',
            contract_name: name,
            chaiId,
            method,
            params: jsonP === '{}' ? '' : jsonP
    })
    if (code !== 0) {
      throw new Error(msg);
    } else {
      message.success({
        content: msg
      });
    }
    // const ticket = Date.now().toString();
    // (window as any).chainMaker.invokeUserContract({
    //   body: {
    //     contractName: name,
    //     method,
    //     params: [
    //       ...extraList.filter(
    //         (item) => item.key.trim() !== '' && item.value.trim() !== ''
    //       )].reduce((val:any, item) => {
    //       val[item.key] = item.value;
    //       return val;
    //     }, {})
    //   },
    //   ticket
    // });
    // setNotificationEvent({
    //   operation: 'invokeUserContract',
    //   contractName: name,
    //   method,
    //   eventId: ticket
    // }, ticket);
    // (window as any).chainMaker.sendRequest('invokeUserContract', {
    //   body: {
    //     contractName: name,
    //     method,
    //     params: [
    //       ...extraList.filter(
    //         (item) => item.key.trim() !== '' && item.value.trim() !== ''
    //       )].reduce((val:any, item) => {
    //       val[item.key] = item.value;
    //       return val;
    //     }, {})
    //   },
    //   contractName: name
    // }, (res:any) => {
    //   console.log(res);
    // });
    // server?.pluginInvokeContract({
    //   contractName: name,
    //   params: [
    //     ...extraList.filter(
    //       (item) => item.key.trim() !== '' && item.value.trim() !== ''
    //     )],
    //   method
    // });
  }, [customAddress, contractAddress, customMethod, contractMethod, extraList, platform, chaiId, virtualMachine]);

  useEffect(() => {
    const name = contractAddress === 'custom' ? customAddress : contractAddress;
    const method = contractMethod === 'custom' ? customMethod : contractMethod;
    if (!name || !method) {
      return;
    }
    const info = getLocalStorage('call', name, method);
    setExtraList(info || getListInit());
  }, [customAddress, contractAddress, contractMethod, customMethod]);

  useEffect(() => {
    const name = contractAddress === 'custom' ? customAddress : contractAddress;
    const method = contractMethod === 'custom' ? customMethod : contractMethod;
    if (!name || !method) {
      return;
    }

    setLocalStorage('call', name, method, extraList);
  }, [extraList]);
  const platformOptions = [{ value: 'linux_amd64', text: 'linux_amd64' },{ value: 'linux_arm64', text: 'linux_arm64' }];

  return (
    <div style={style} className="nav_tab">
      <Form className='side_tab_form' layout="vertical">
        <Form.Item label="合约执行架构">
          <Select
            className="set-height"
            size="full"
            matchButtonWidth
            appearance="button"
            options={platformOptions}
            value={platform}
            onChange={setPlatform}
          />
        </Form.Item>
        <Form.Item label="运行链ID">
          <Input
            value={chaiId}
            onChange={setchaiId}
            className="set-height"
            placeholder='请输入发运行链ID'
            size="full"/>
        </Form.Item>
        <Form.Item label="合约语言类型">
          <Select
            className="set-height"
            size="full"
            matchButtonWidth
            appearance="button"
            options={VirtualMachineOptions}
            value={virtualMachine}
            onChange={(value) => setVirtualMachine(value)}
          />
        </Form.Item>
        <Form.Item label={
          <div className='form-label'>
            <div>选择合约(已部署)</div>
            <Button type='link' onClick={() => setEditDeployContractsVisible(true)}>管理</Button>
          </div>
        }>
          <Select
            className="set-height"
            size="full"
            matchButtonWidth
            appearance="button"
            options={[...contractOption.map((item: HasDeployContractListResponse) => ({ value: item.contractName, text: item.contractName })), { value: 'custom', text: '自定义' }]}
            value={contractAddress}
            onChange={(value) => {
              setContractAddress(value);
              setCustomAddress('');
            }}
          />
          {contractAddress === 'custom' && (
            <Input
              className="select-next-input"
              size="full"
              value={customAddress}
              onChange={(val) => setCustomAddress(val)}
            />
          )}
        </Form.Item>
        <Form.Item label={
          <>
            合约方法 
            <Bubble
              arrowPointAtCenter
              placement="top-start"
              content="此处为了展示更加直观，无论是invoke合约，还是query合约，都采用invoke的方式去调用，故而query类的交易也会上链。"
            >
              <Icon type="help" />
            </Bubble>
          </>
        }>
          {/* <Select
            className="set-height"
            size="full"
            matchButtonWidth
            appearance="button"
            options={[...(methodOption ? methodOption.map(item => ({ value: item, text: item })) : []), { value: 'custom', text: '自定义' }]}
            value={contractMethod}
            onChange={(value) => {
              setContractMethod(value);
              setCustomMethod('');
            }}
          /> */}
          {contractMethod === 'custom' && (
            <Input
              className="select-next-input"
              size="full"
              value={customMethod}
              onChange={(val) => setCustomMethod(val)}
            />
          )}
        </Form.Item>
        <Form.Item label="" className="hide-label">
          <div className="tea-mt-4n">
            <KeyValueList
              value={extraList}
              onChange={(item: Array<KeyValueItem>) => {
                setExtraList(item);
              }}
            />
          </div>
        </Form.Item>
        <div className="form-operate-action  tea-mt-4n">
          <Button type="primary" className="full-btn" onClick={resetHandle}>
            重置数据
          </Button>
          <Button
            type="primary"
            className="full-btn"
            // disabled={!isPluginReady}
            onClick={invokeContract}
          // loading={submit}
          >
            合约调用
          </Button>
        </div>
      </Form>
      {/* {style?.display === 'block' && <ExecResult />} */}
    </div>
  );
}
